﻿namespace MicroCloud.Utils
{
    /// <summary>
    /// 程序集管理器
    /// </summary>
    public static class AssemblyManager
    {
        //字段
        private static Assembly[] _allAssemblies;
        private static Type[] _allExportTypes;

        /// <summary>
        /// 静态构造函数(程序集管理器)
        /// </summary>
        static AssemblyManager()
        {
            AssemblyFilterFunc = name =>
            {
                return name.Name != null && !Filters.Any(m => name.Name.StartsWith(m));
            };
        }

        #region 静态属性
        /// <summary>
        /// 获取 程序集过滤条件
        /// </summary>
        public static string[] Filters { get; private set; } = { "dotnet-", "Microsoft.", "mscorlib", "netstandard", "System", "Windows", "NPOI." };

        /// <summary>
        /// 设置 程序集过滤器
        /// </summary>
        public static Func<AssemblyName, bool> AssemblyFilterFunc { private get; set; }

        /// <summary>
        /// 获取 所有程序集
        /// </summary>
        public static Assembly[] AllAssemblies
        {
            get
            {
                if (_allAssemblies == null)
                {
                    Init();
                }

                return _allAssemblies;
            }
        }

        /// <summary>
        /// 获取 所有公开类型
        /// </summary>
        public static Type[] AllExportTypes
        {
            get
            {
                if (_allExportTypes == null)
                {
                    Init();
                }

                return _allExportTypes;
            }
        }

        #endregion

        #region 方法
        #region "设置程序集过滤条件"
        /// <summary>
        /// 设置程序集过滤条件
        /// </summary>
        /// <param name="filters">过滤字符(左匹配)</param>
        public static void SetFilters(params string[] filters)
        {
            Filters = filters;
        }
        #endregion
        #region "增加程序集过滤条件"
        /// <summary>
        /// 增加程序集过滤条件
        /// </summary>
        /// <param name="filters">过滤字符(左匹配)</param>
        public static void AppendFilters(params string[] filters)
        {
            var filtersList = Filters.ToList();
            filtersList.AddRange(filters);

            Filters = filtersList.ToArray();
        }
        #endregion
        #region "移除程序集过滤条件"
        /// <summary>
        /// 移除程序集过滤条件
        /// </summary>
        /// <param name="filters">过滤字符(左匹配)</param>
        public static void RemoveFilters(params string[] filters)
        {
            var filtersList = Filters.ToList();
            filtersList.RemoveAll(o => filters.Contains(o));

            Filters = filtersList.ToArray();
        }
        #endregion
        #region "初始化"
        /// <summary>
        /// 初始化
        /// </summary>
        public static void Init()
        {
            Check.NotNull(AssemblyFilterFunc, "AssemblyManager.AssemblyFilterFunc");

            _allAssemblies = DependencyContext.Default.GetDefaultAssemblyNames().Where(AssemblyFilterFunc).Select(Assembly.Load).ToArray();
            _allExportTypes = _allAssemblies.SelectMany(m => m.ExportedTypes).ToArray();
        }
        #endregion
        #region "查找指定条件的类型"
        /// <summary>
        /// 查找指定条件的类型
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static Type[] FindTypes(Func<Type, bool> predicate)
        {
            var types = AllExportTypes.Where(predicate).ToArray();
            return types;
        }
        #endregion
        #region "查找指定基类的实现类型"
        /// <summary>
        /// 查找指定基类的实现类型
        /// </summary>
        /// <typeparam name="TBaseType">基础类型</typeparam>
        /// <param name="hasParent">包含父类(拥有派生类的中间类)</param>
        /// <param name="hasAbstract">包含抽象类</param>
        /// <returns>实现类型集合</returns>
        public static Type[] FindTypesByBase<TBaseType>(bool hasParent = false, bool hasAbstract = false)
        {
            Type baseType = typeof(TBaseType);
            var types = FindTypesByBase(baseType, hasParent, hasAbstract);
            return types;
        }
        #endregion
        #region "查找指定基类的实现类型"
        /// <summary>
        /// 查找指定基类的实现类型
        /// </summary>
        /// <param name="baseType">基础类型</param>
        /// <param name="hasParent">包含父类(拥有派生类的中间类)</param>
        /// <param name="hasAbstract">包含抽象类</param>
        /// <returns>实现类型集合</returns>
        public static Type[] FindTypesByBase(Type baseType, bool hasParent = false, bool hasAbstract = false)
        {
            var types = AllExportTypes?.Where(type => type.IsDeriveClassFrom(baseType, hasAbstract))?.Distinct()?.ToArray() ?? Array.Empty<Type>();
            if (hasParent)
            {
                return types;
            }
            var subTypes = new List<Type>();
            foreach (var type in types)
            {

                if (!(types.Where(t => t.IsDeriveClassFrom(type, hasAbstract))?.Distinct()?.ToList()?.Count > 0))
                {
                    subTypes.Add(type);
                }
            }
            return subTypes.ToArray();
        }
        #endregion
        #region "查找指定Attribute特性的实现类型"
        /// <summary>
        /// 查找指定Attribute特性的实现类型
        /// </summary>
        /// <typeparam name="TAttribute"></typeparam>
        /// <param name="inherit"></param>
        /// <returns></returns>
        public static Type[] FindTypesByAttribute<TAttribute>(bool inherit = true)
        {
            Type attributeType = typeof(TAttribute);
            var types = FindTypesByAttribute(attributeType, inherit);
            return types;
        }
        #endregion
        #region "查找指定Attribute特性的实现类型"
        /// <summary>
        /// 查找指定Attribute特性的实现类型
        /// </summary>
        /// <param name="attributeType"></param>
        /// <param name="inherit"></param>
        /// <returns></returns>
        public static Type[] FindTypesByAttribute(Type attributeType, bool inherit = true)
        {
            var types = AllExportTypes.Where(type => type.IsDefined(attributeType, inherit)).Distinct().ToArray();
            return types;
        }
        #endregion

        #region "判断当前类型是否存在派生类型"
        /// <summary>
        /// 判断当前类型是否存在派生类型
        /// </summary>
        /// <typeparam name="TType">要判断的类型</typeparam>
        /// <param name="hasAbstract">包含抽象类</param>
        /// <returns></returns>
        public static bool HasDerivedClass<TType>(bool hasAbstract = false)
        {
            Type type = typeof(TType);
            return HasDerivedClass(type, hasAbstract);
        }
        #endregion
        #region "判断当前类型是否存在派生类型"
        /// <summary>
        /// 判断当前类型是否存在派生类型
        /// </summary>
        /// <param name="type">要判断的类型</param>
        /// <param name="hasAbstract">包含抽象类</param>
        /// <returns></returns>
        public static bool HasDerivedClass(Type type, bool hasAbstract = false)
        {
            var types = FindTypesByBase(type, hasAbstract);
            return types?.Length > 0;
        }
        #endregion

        #endregion

    }
}
